package edu.ustb.aur.moldpackage;

import java.util.*;

import edu.ustb.aur.assetpackage.Asset;
import edu.ustb.aur.assetpackage.AssetService;
import edu.ustb.aur.myenum.MoldEnum;
import edu.ustb.aur.myenum.RightEnum;
import edu.ustb.aur.rightpackage.AbstractRight;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

import javax.annotation.PostConstruct;

/** @author Maker-Mr.Yao 房屋类资产的生成模版 */
public class HouseMold extends AbstractMold {

//    @Autowired
//    private AssetService assetService;
//
//    private static HouseMold houseMold;

    /**
     * 添加日志对象
     * TODO 与mold序列化与反序列化存在冲突，在findMold时，将log注释掉
     */
//    public Logger log = LoggerFactory.getLogger(getClass());

//    /**
//     * 通过@PostConstruct实现初始化bean之前进行的操作
//     */
//    @PostConstruct
//    public void init() {
//        houseMold = this;
//        houseMold.assetService = this.assetService;
//    }
    /** 默认构造函数 */
    public HouseMold() {
        // 调用父类默认构造函数
        super();
        type = "HOUSE_MOLD";
    }

    /**
     * 带参构造函数
     *
     * @param moldMap
     *            资产对象与权利对象的映射
     */
    public HouseMold(HashMap<RightEnum, AbstractRight> moldMap, double threshold) {
        // 调用父类含参构造函数
        super(moldMap, threshold);
        type = "HOUSE_MOLD";
    }

    /**
     * 售卖操作，判断各权利是否均操作阈值，符合条件就执行。同意者的rightMap各权利之和超过阈值，强制执行此操作，原权利映射注销，新的权利映射建立 规定了售卖操作需要具有的权利，规定了售卖操作需要完成的权利转移
     * 目前假定进行售卖操作，需要具有收益权，占有权，处分权，并且其具有的比例操作阈值
     *
     * @param moldMap
     *            资产对象与权利对象的映射hashMap
     * @param froms
     *            调用此操作的同意者数组
     * @param toRightMap
     *            此操作执行成功后，接收者的分配rightMap
     * @return true or false
     */
    @Override
    public boolean sell(HashMap<RightEnum, AbstractRight> moldMap, String[] froms, HashMap<String, Double> toRightMap) {

        // 1. 通过isHasImplementRight函数判断是否具有相应的操作权利
        if (!isHasImplementRight(MoldEnum.SELL_MOLD, moldMap, froms, this.threshold)) {
            // 没有相关操作权利
//            log.error("该用户组无权对该资产进行操作");
            return false;
        }

        // 用户具有相关权利
//        log.info("该用户组有权对该资产进行操作");

        // 2. 调用对应的权利注销函数，注销所有映射

        // 2.1 先删除具有处分权的卖家的使用权，防止卖家在卖房后还具有使用权，租房者使用权不变
        Set<String> userDisposeSet = new HashSet<>(moldMap.get(RightEnum.DISPOSE_RIGHT).rightMap.keySet());
        for (String userAddress : userDisposeSet) {
            if (moldMap.get(RightEnum.USE_RIGHT).rightMap.get(userAddress) != null) {
                moldMap.get(RightEnum.USE_RIGHT).deleteRight(userAddress,
                        moldMap.get(RightEnum.USE_RIGHT).rightMap.get(userAddress));
            }
        }

        // 2.2 注销卖家的其他权利映射
        for (RightEnum rightEnum : operateTypeRightList(MoldEnum.SELL_MOLD)) {
            // 删除moldMap中rightEnum的映射关系
            // 在sell操作中，一旦可以进行sell，应该注销掉所有用户的权利，而不仅仅是froms里的用户
            Set<String> userAddressSet = new HashSet<>(moldMap.get(rightEnum).rightMap.keySet());
            for (String userAddress : userAddressSet) {
                moldMap.get(rightEnum).deleteRight(userAddress, moldMap.get(rightEnum).rightMap.get(userAddress));
            }
        }

        // 3. 调用对应的权利建立函数
        // 3.1 判断使用权是否具有映射，具有则该房屋正在出租中，不修改，否则，将建立接收者的映射
        // TODO 可能不仅仅只有使用权需要判断，而是使用权+占有权，即居住权
        if (moldMap.get(RightEnum.USE_RIGHT).rightMap.isEmpty()) {
            for (String userAddress : toRightMap.keySet()) {
                moldMap.get(RightEnum.USE_RIGHT).initRight(userAddress, toRightMap.get(userAddress));
                if (!moldMap.containsKey(RightEnum.USE_RIGHT)) {
                    // 不存在则返回false，映射关系应该上一步中添加了
                    return false;
                }
            }
        } else {
            System.out.println("房屋正在出租中！");
        }
        // 3.2 新建卖家其他权利映射
        for (RightEnum rightEnum : operateTypeRightList(MoldEnum.SELL_MOLD)) {
            for (String userAddress : toRightMap.keySet()) {
                if (!rightEnum.equals(RightEnum.USE_RIGHT)) {
                    moldMap.get(rightEnum).initRight(userAddress, toRightMap.get(userAddress));
                }
                if (!moldMap.containsKey(rightEnum)) {
                    // 不存在则返回false，映射关系应该上一步中添加了
                    return false;
                }
            }
        }
        return true;
    }

    /**
     * 租赁操作，判断各权利是否均操作阈值，符合条件就执行。 规定了租赁操作需要具有的权利，规定了租赁操作需要完成的权利转移 目前假定进行租赁操作，需要具有收益权，使用权，占有权，并且其具有的比例操作阈值
     *
     * @param moldMap
     *            资产对象与权利对象的映射hashMap
     * @param froms
     *            调用此操作的同意者数组
     * @param toRightMap
     *            此操作执行成功后，接收者的分配rightMap
     * @return true or false
     */
    @Override
    public boolean lease(HashMap<RightEnum, AbstractRight> moldMap, String[] froms,
        HashMap<String, Double> toRightMap) {
        // 1. 通过isHasImplementRight函数判断是否具有相应的操作权利
        if (!isHasImplementRight(MoldEnum.LEASE_MOLD, moldMap, froms, this.threshold)) {
            // 没有相关操作权利
            return false;
        }

        // 2. 调用对应的权利注销函数，注销所有映射
        for (RightEnum rightEnum : operateTypeRightList(MoldEnum.LEASE_MOLD)) {
            // 删除moldMap中rightEnum的映射关系
            // 在租赁关系中，同意出租房子的人将自己对房子的使用权和占有权交给租客，但值得注意的是这不包括房子的收益权
            Set<String> userAddressSet = new HashSet<>(moldMap.get(rightEnum).rightMap.keySet());
            for (String userAddress : userAddressSet) {
                if (!rightEnum.equals(RightEnum.USUFRUCT_RIGHT) && !rightEnum.equals(RightEnum.DISPOSE_RIGHT)) {
                    moldMap.get(rightEnum).deleteRight(userAddress, moldMap.get(rightEnum).rightMap.get(userAddress));
                }
            }
        }

        // 3. 调用对应的权利建立函数
        for (RightEnum rightEnum : operateTypeRightList(MoldEnum.LEASE_MOLD)) {
            for (String userAddress : toRightMap.keySet()) {
                if (!rightEnum.equals(RightEnum.USUFRUCT_RIGHT) && !rightEnum.equals(RightEnum.DISPOSE_RIGHT)) {
                    moldMap.get(rightEnum).initRight(userAddress, toRightMap.get(userAddress));
                }
                if (!moldMap.containsKey(rightEnum)) {
                    // 不存在则返回false，映射关系应该上一步中添加了
                    return false;
                }
            }
        }
        return true;
    }

    /**
     * 租赁返回操作
     *
     * @param moldMap
     *            资产对象与权利对象的映射hashMap
     * @param froms
     *            调用此操作的同意者数组
     * @param toRightMap
     *            此操作执行成功后，接收者的分配rightMap
     * @return true or false
     */
    @Override
    public boolean leaseReturn(HashMap<RightEnum, AbstractRight> moldMap, String[] froms,
                               HashMap<String, Double> toRightMap) {
        // 1. 通过isHasImplementRight函数判断是否具有相应的操作权利
        if (!isHasImplementRight(MoldEnum.LEASEReturn_MOLD, moldMap, froms, this.threshold)) {
            // 没有相关操作权利
//            log.error("该用户组无权对该资产进行操作");
            return false;
        }

        // 2. 调用对应的权利注销函数，注销所有映射
        for (RightEnum rightEnum : operateTypeRightList(MoldEnum.LEASEReturn_MOLD)) {
            // 删除moldMap中rightEnum的映射关系
            for (String userAddress : froms) {
                if (!rightEnum.equals(RightEnum.USUFRUCT_RIGHT) && !rightEnum.equals(RightEnum.DISPOSE_RIGHT)) {
                    moldMap.get(rightEnum).deleteRight(userAddress, moldMap.get(rightEnum).rightMap.get(userAddress));
                }
            }
        }

        // 3. 调用对应的权利建立函数
        for (RightEnum rightEnum : operateTypeRightList(MoldEnum.LEASEReturn_MOLD)) {
            for (String userAddress : toRightMap.keySet()) {
                if (!rightEnum.equals(RightEnum.USUFRUCT_RIGHT) && !rightEnum.equals(RightEnum.DISPOSE_RIGHT)) {
                    moldMap.get(rightEnum).initRight(userAddress, toRightMap.get(userAddress));
                }
                if (!moldMap.containsKey(rightEnum)) {
                    // 不存在则返回false，映射关系应该上一步中添加了
                    return false;
                }
            }
        }
        return true;
    }

    /**
     * 抵押操作，判断各权利是否均操作阈值，符合条件就执行。 规定了抵押操作需要具有的权利，规定了抵押操作需要完成的权利转移 目前假定进行抵押操作，需要具有处分权，并且其具有的比例操作阈值
     * 由抵押操作产生的担保物权，不属于四项基本权利，关于这点还值得商榷，目前的采取的办法是将处分权移交（但明显没道理）
     * 
     * @param moldMap
     *            资产对象与权利对象的映射hashMap
     * @param froms
     *            调用此操作的同意者数组
     * @param toRightMap
     *            此操作执行成功后，接收者的分配rightMap
     * @return true or false
     */
    @Override
    public boolean mortgage(HashMap<RightEnum, AbstractRight> moldMap, String[] froms,
        HashMap<String, Double> toRightMap) {
        // 1. 通过isHasImplementRight函数判断是否具有相应的操作权利
        if (!isHasImplementRight(MoldEnum.MORTGAGE_MOLD, moldMap, froms, this.threshold)) {
            // 没有相关操作权利
            return false;
        }

        // 2. 调用对应的权利注销函数，注销所有映射
        // TODO 抵押这是不是也有问题？我有处分权，我可以将房子进行抵押，但这并不意味着我将房子的处分权转交
        for (RightEnum rightEnum : operateTypeRightList(MoldEnum.MORTGAGE_MOLD)) {
            // 删除moldMap中rightEnum的映射关系
            Set<String> userAddressSet = new HashSet<>(moldMap.get(rightEnum).rightMap.keySet());
            for (String userAddress : userAddressSet) {
                moldMap.get(rightEnum).deleteRight(userAddress, moldMap.get(rightEnum).rightMap.get(userAddress));
            }
        }

        // 3. 调用对应的权利建立函数
        for (RightEnum rightEnum : operateTypeRightList(MoldEnum.MORTGAGE_MOLD)) {
            for (String userAddress : toRightMap.keySet()) {
                moldMap.get(rightEnum).initRight(userAddress, toRightMap.get(userAddress));
                if (!moldMap.containsKey(rightEnum)) {
                    // 不存在则返回false，映射关系应该上一步中添加了
                    return false;
                }
            }
        }
        return true;
    }

    /**
     * 馈赠操作，判断各权利是否均操作阈值，符合条件就执行。 规定了馈赠操作需要具有的权利，规定了馈赠操作需要完成的权利转移 目前假定进行馈赠操作，需要具有收益权，占有权，处分权，并且其具有的比例操作阈值
     * 同样存在和sell相同的问题，对于买房不破租的处理
     * 
     * @param moldMap
     *            资产对象与权利对象的映射hashMap
     * @param froms
     *            调用此操作的同意者数组
     * @param toRightMap
     *            此操作执行成功后，接收者的分配rightMap
     * @return true or false
     */
    @Override
    public boolean gift(HashMap<RightEnum, AbstractRight> moldMap, String[] froms, HashMap<String, Double> toRightMap) {
        // 1. 通过isHasImplementRight函数判断是否具有相应的操作权利
        if (!isHasImplementRight(MoldEnum.GIFT_MOLD, moldMap, froms, this.threshold)) {
            // 没有相关操作权利
            return false;
        }

        // 2. 调用对应的权利注销函数，注销所有映射
        for (RightEnum rightEnum : operateTypeRightList(MoldEnum.GIFT_MOLD)) {
            // 删除moldMap中rightEnum的映射关系
            Set<String> userAddressSet = new HashSet<>(moldMap.get(rightEnum).rightMap.keySet());
            for (String userAddress : userAddressSet) {
                moldMap.get(rightEnum).deleteRight(userAddress, moldMap.get(rightEnum).rightMap.get(userAddress));
            }
        }

        // 3. 调用对应的权利建立函数
        for (RightEnum rightEnum : operateTypeRightList(MoldEnum.GIFT_MOLD)) {
            for (String userAddress : toRightMap.keySet()) {
                moldMap.get(rightEnum).initRight(userAddress, toRightMap.get(userAddress));
                if (!moldMap.containsKey(rightEnum)) {
                    // 不存在则返回false，映射关系应该上一步中添加了
                    return false;
                }
            }
        }
        return true;
    }

    /**
     * 销毁操作，判断各权利是否均操作阈值，符合条件就执行。 规定了销毁操作需要具有的权利，规定了销毁操作需要完成的权利转移 目前假定进行销毁操作，需要具有收益权，占有权，处分权，使用权，并且其具有的比例操作阈值
     *
     * @param moldMap
     *            资产对象与权利对象的映射hashMap
     * @param froms
     *            调用此操作的同意者数组
     * @return true or false
     */
    @Override
    public boolean destroy(HashMap<RightEnum, AbstractRight> moldMap, String... froms) {
        // 1. 通过isHasImplementRight函数判断是否具有相应的操作权利
        if (!isHasImplementRight(MoldEnum.DESTROY_MOLD, moldMap, froms, this.threshold)) {
            // 没有相关操作权利
            return false;
        }

        // 2. 调用对应的权利注销函数，注销所有映射
        for (RightEnum rightEnum : operateTypeRightList(MoldEnum.DESTROY_MOLD)) {
            // 删除moldMap中rightEnum的映射关系
            moldMap.remove(rightEnum);
        }
        return true;
    }

    /**
     *
     * @param assetId
     *            资产id
     * @param froms
     *            调用此操作的同意者数组
     * @param asset
     *            资产对象
     * @param moldMap
     *            资产对象与权利对象的映射hashMap
     * @return
     */
    @Override
    public boolean update(String assetId, String[] froms, Asset asset, HashMap<RightEnum, AbstractRight> moldMap) {
        // 通过isHasImplementRight函数判断是否具有相应的操作权利
        if (!isHasImplementRight(MoldEnum.UPDATE_MOLD, moldMap, froms, this.threshold)) {
            // 没有相关操作权利
//            log.error("该用户组无权对该资产进行操作");
            return false;
        }
//        log.info("该用户组有权对该资产进行操作");
        return true;
    }

    /**
     * 各操作规则需要的权利集合定义
     *
     * @param operateType
     *            资产的操作方法
     * @return 所需要的权利集合 TODO 操作规则需要补充或者修正
     */
    @Override
    public List<RightEnum> operateTypeRightList(MoldEnum operateType) {
        switch (operateType) {
            case SELL_MOLD:
            case GIFT_MOLD:
            case LEASE_MOLD:
            case DESTROY_MOLD:
                return Arrays.asList(RightEnum.USUFRUCT_RIGHT, RightEnum.USE_RIGHT, RightEnum.POSSESS_RIGHT,
                    RightEnum.DISPOSE_RIGHT);
            case UPDATE_MOLD:
            case MORTGAGE_MOLD:
                return Arrays.asList(RightEnum.DISPOSE_RIGHT);
            case LEASEReturn_MOLD:
                return Arrays.asList(RightEnum.USE_RIGHT, RightEnum.POSSESS_RIGHT);
            default:
                return Collections.emptyList();
        }
    }
}
